package com.zhengxyou.demo531;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;

/**
 * Created by zhengxyou@163.com on 2018/5/31.
 */
public class SearchViewDemo extends View {
    private Paint mPaint;
    private Path path_search;
    private Path path_circle;
    private float mCenterX;
    private float mCenterY;
    private float mCurrentValue;

    private State mState = State.Default;
    private final long defaultDuration = 1500;
    private ValueAnimator searchingAnimator;
    private ValueAnimator startingAnimator;
    private ValueAnimator endAnimator;

    private ValueAnimator.AnimatorListener animatorListener;
    private ValueAnimator.AnimatorUpdateListener updateListener;


    private Handler mHandler;

    private PathMeasure measure;

    private boolean isOVer = false;

    enum State {
        Default,//默认状态
        Search,//搜索中
        Start,//开始搜索
        End//结束
    }

    public SearchViewDemo(Context context) {
        this(context, null);
    }

    public SearchViewDemo(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initPaint();
        initPath();
        initListener();
        initAnimator();
        initHandler();
    }

    @SuppressLint("HandlerLeak")
    private void initHandler() {
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case 2:
                        isOVer = false;
                        mState = State.Start;
                        startingAnimator.start();
                        break;
                    case 1:
                        if (!isOVer) {
                            mState = State.Search;
                            searchingAnimator.start();
                        } else {
                            mState = State.End;
                            endAnimator.start();
                        }
                        break;
                    case 3:
                        mState = State.Default;
                        break;
                }
            }
        };
    }

    private void initListener() {
        updateListener = new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCurrentValue = (float) animation.getAnimatedValue();
                invalidate();
            }
        };

        animatorListener = new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (mState == State.End) {
                    mHandler.sendEmptyMessage(3);
                } else {
                    mHandler.sendEmptyMessage(1);
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        };
    }

    private void initAnimator() {
        searchingAnimator = ValueAnimator.ofFloat(0, 1).setDuration(defaultDuration);
        searchingAnimator.setInterpolator(new AccelerateDecelerateInterpolator());

        startingAnimator = ValueAnimator.ofFloat(0, 1).setDuration(defaultDuration);
        endAnimator = ValueAnimator.ofFloat(0, 1).setDuration(defaultDuration);

        searchingAnimator.addListener(animatorListener);
        startingAnimator.addListener(animatorListener);
        endAnimator.addListener(animatorListener);
        endAnimator.addUpdateListener(updateListener);
        startingAnimator.addUpdateListener(updateListener);
        searchingAnimator.addUpdateListener(updateListener);
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setColor(Color.WHITE);
        mPaint.setAntiAlias(true);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(15);
        mPaint.setStyle(Paint.Style.STROKE);
    }

    private void initPath() {
        path_search = new Path();
        path_circle = new Path();
        measure = new PathMeasure();

        RectF searchRectf = new RectF(-100, -100, 100, 100);
        RectF circleRectf = new RectF(-50, -50, 50, 50);

        path_search.addArc(searchRectf, 45, -359.9f);
        path_circle.addArc(circleRectf, 45, 359.9f);

        measure.setPath(path_search, false);
        float[] pos = new float[2];
        measure.getPosTan(0, pos, null);

        path_circle.lineTo(pos[0], pos[1]);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mCenterX = w / 2;
        mCenterY = h / 2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.WHITE);
        canvas.translate(mCenterX, mCenterY);
        canvas.drawColor(Color.parseColor("#0082D7"));

        switch (mState) {
            case Default:
                canvas.drawPath(path_circle, mPaint);
                break;
            case Start:
                Path path = new Path();
                measure.setPath(path_circle, false);
                measure.getSegment(measure.getLength() * mCurrentValue, measure.getLength(), path, true);
                canvas.drawPath(path, mPaint);
                break;
            case Search:
                measure.setPath(path_search, false);
                Path dst = new Path();
                float stop = measure.getLength() * mCurrentValue;
                float start = (float) (stop - (0.5 - Math.abs(mCurrentValue - 0.5)) * 200);
                measure.getSegment(start, stop, dst, true);
                canvas.drawPath(dst, mPaint);
                break;
            case End:
                measure.setPath(path_circle, false);
                Path dst2 = new Path();
                measure.getSegment(measure.getLength() - mCurrentValue * measure.getLength(), measure.getLength(), dst2, true);
                canvas.drawPath(dst2, mPaint);
                break;
        }
    }

    public void onStartSearch() {
        mHandler.sendEmptyMessage(2);
    }

    public void endSearch() {
        isOVer = true;
    }
}
